package com.ahoi.service;

import com.ahoi.common.constant.CommonEnum;
import com.ahoi.common.constant.Constants;
import com.ahoi.common.utils.DateUtils;
import com.ahoi.common.utils.JsoupUtils;
import com.ahoi.common.utils.StringUtils;
import com.ahoi.common.utils.ThreadUtils;
import com.ahoi.dao.BookInfoDao;
import com.ahoi.model.BookInfo;
import com.ahoi.model.ErrorUrl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Auther: ahoi
 * @Date: 2018/4/28 17:19
 * @Description: 小说
 */
@Service
public class BookInfoService {
    private static Logger logger = LoggerFactory.getLogger(BookInfoService.class);

    @Autowired
    private BookInfoDao bookInfoDao;
    @Autowired
    private ErrorUrlService errorUrlService;

    public PageInfo<BookInfo> listPage(BookInfo query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        Page<BookInfo> page = bookInfoDao.listPage(query);
        return new PageInfo<>(page);
    }

    public List<BookInfo> listData(BookInfo query) {
        Page<BookInfo> page = bookInfoDao.listPage(query);
        return page.getResult();
    }

    /**
     * 验证是否存在该ID的数据
     */
    public boolean checkExists(Integer id) {
        return bookInfoDao.checkExists(id) > 0;
    }

    /**
     * 插入一条，保存基本信息
     */
    public void insertOne(Integer id, String title, String imgUrl) {
        bookInfoDao.insertOne(id, title, imgUrl);
    }

    /**
     * 重置所有记录的状态为未更新
     */
    public void updatedToInit() {
        BookInfo model = new BookInfo();
        model.setUpdated(CommonEnum.NO.getCode());
        updateOne(model);
    }

    /**
     * 记录的状态为已更新
     */
    public void updatedToUpdated(List<BookInfo> bookInfos) {
        List<Integer> idList = bookInfos.stream().map(o -> o.getId()).collect(Collectors.toList());
        BookInfo model = new BookInfo();
        model.setUpdated(CommonEnum.YES.getCode());
        model.setIdList(idList);
        updateOne(model);
    }

    /**
     * 更新，保存详细信息
     */
    public void updateOne(BookInfo model) {
        bookInfoDao.updateOne(model);
    }

    /**
     * 获取总页码
     */
    public Integer getTotalPage(String url) throws Exception {
        Integer totalPage = 0;
        url = url.replace("{pageNum}", String.valueOf(0));
        Document doc = Jsoup.connect(url).get();

        // 获取总页数和总条数
        String pageInfo = doc.select(".pagination span").text();
        if (StringUtils.isNotEmpty(pageInfo)) {
            // 共5263页 157870条
            pageInfo = pageInfo.replaceAll("[共页条]", "");
            String[] split = pageInfo.split(" ");
            if (split.length == 2) {
                totalPage = Integer.parseInt(split[0]);
            }
        }
        return totalPage;
    }

    /**
     * 扫描小说
     */
    public void scanAndInsertBooks(int pageStart, int pageEnd, String url) {
        for (int i = pageStart; i <= pageEnd; i++) {
            try {

                // 获取页面内容
                String newUrl = url.replace("{pageNum}", String.valueOf(i));
                Document doc = JsoupUtils.loadURL(newUrl);

                // 处理请求失败
                if (doc == null) {
                    errorUrlService.insertOne(newUrl);
                    continue;
                }

                // 解析内容
                BookInfo bookInfo;
                Elements divList = doc.select("#waterfall .item");
                for (Element div : divList) {
                    bookInfo = new BookInfo();
                    bookInfo.setId(Integer.parseInt(div.select(".title a").attr("href").replaceAll("/", "")));
                    bookInfo.setTitle(div.select(".title a").text());
                    bookInfo.setImgUrl(div.select(".pic img").attr("data-original"));

                    // 数据库不存在才插入
                    if (!checkExists(bookInfo.getId())) {
                        insertOne(bookInfo.getId(), bookInfo.getTitle(), bookInfo.getImgUrl());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 本次线程循环请求结束
        ThreadUtils.decThreadAliveCount();

        // 判断是否所有线程的请求都结束，开始从失败的请求列表里面重新请求
        if (ThreadUtils.getThreadAliveCount() == 0) {
            logger.info("all request is over...");
            scanFromErrorUrl();
        }
    }

    /**
     * 从失败请求里面重新扫描
     */
    public int scanFromErrorUrl() {
        // 获取列表后立刻删除
        List<ErrorUrl> errorUrls = errorUrlService.listAll();

        // 重新发起新的线程请求
        int size = errorUrls.size();
        if (size > 0) {
            logger.info("more(" + size + ") request is repeated send...");
            ThreadUtils.iniThreadAliveCount(size);
            errorUrlService.deleteAll();
            for (ErrorUrl item : errorUrls) {
                ThreadUtils.startNewThread("scan-and-insert-re-" + item.getId(), new Runnable() {
                    @Override
                    public void run() {
                        scanAndInsertBooks(1, 1, item.getUrl());
                    }
                });
            }
        } else {
            // 标记扫描服务结束
            Constants.SERVICE_STARTING = false;
            logger.info("none request...");
        }
        return size;
    }

    /**
     * 加载详情
     */
    public void loadForDetail(List<BookInfo> bookInfos, String bookListUrl) {
        if (bookInfos.size() > 0) {
            for (BookInfo bookInfo : bookInfos) {
                String newUrl = bookListUrl.replace("{id}", String.valueOf(bookInfo.getId()));
                Document doc = JsoupUtils.loadURL(newUrl);

                // 处理请求失败
                if (doc == null) {
//                    errorUrlService.insertOne(newUrl);
                    continue;
                }

                // 简介
                doc.select("#aboutbook a").remove();
                doc.select("#aboutbook h3").remove();
                bookInfo.setInfoDesc(doc.select("#aboutbook").html());

                // 作者
                bookInfo.setAuthor(doc.select("#infobox .username a").text());

                // 最新章节
                bookInfo.setLastestCatalog(doc.select("#info .tag a").text());

                // 最后更新时间
                Date date = DateUtils.createDate(doc.select("#info .tag .time").text());
                if (date != null) {
                    bookInfo.setLastUpdateTime(new Timestamp(date.getTime()));
                }

                // 作品类别
                bookInfo.setType(doc.select("#mainright .infonum ul li:eq(0)").text().replaceAll("作品类别([：:])", ""));

                // 总章节
                String totalCatalog = doc.select("#mainright .infonum ul li:eq(1)").text().replaceAll("[^\\d]", "");
                if (StringUtils.isNotEmpty(totalCatalog)) {
                    bookInfo.setTotalCatalog(Integer.parseInt(totalCatalog));
                }

                // 标签
                bookInfo.setAlias(doc.select("#mainright .infonum ul li:eq(5)").text().replaceAll("标签([：:])", ""));

                // 更新
                bookInfo.setUpdated(CommonEnum.YES.getCode());
                updateOne(bookInfo);
                logger.info("one book is updated...");
            }
        }
    }

}
